package aries.database;

/******************************************************************************
 * You may modify, publish, and use Aries for your own purpose. BUT
 * DON'T REMOVE THIS TEXT.
 * Visit my facebook: http://www.facebook.com/freeskies or
 * Follow my twitter: @freeskys
 *
 *
 * Author: Harditya Rahmat Ramadhan
 * Licence: GPLv2
 *****************************************************************************/

import aries.utils.TextUtil;
import aries.utils.Util;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Arrays;

public class Table {

    private String table;
    private String[] field;
    private String[] type;
    private String[] length;
    private Boolean autoIncrement = false;

    /**
     * Constructor.
     * 
     * @param table 
     */
    public Table(Table table) {
        this.table = table.getTable();
    }
    
    /**
     * Constructor.
     *
     * @param table
     */
    public Table(String table) {
        this.table = table;
    }
    
    /**
     * Constructor.
     * 
     * @param table
     * @param autoIncrement 
     */
    public Table(Table table, Boolean autoIncrement) {
        this.table = table.getTable();
        this.autoIncrement = autoIncrement;
    }
    
    /**
     * Constructor.
     * 
     * @param table
     * @param autoIncrement 
     */
    public Table(String table, Boolean autoIncrement) {
        this.table = table;
        this.autoIncrement = autoIncrement;
    }
    
    /**
     * Constructor.
     * 
     * @param table
     * @param field 
     */
    public Table(Table table, Field field) {
        this.table = table.getTable();
        this.field = field.getField();
        this.type = field.getType();
        this.length = field.getLength();
    }

    /**
     * Constructor.
     *
     * @param table
     * @param field
     */
    public Table(String table, Field field) {
        this.table = table;
        this.field = field.getField();
        this.type = field.getType();
        this.length = field.getLength();
    }
    
    /**
     * Constructor.
     * 
     * @param table
     * @param field
     * @param autoIncrement 
     */
    public Table(Table table, Field field, Boolean autoIncrement) {
        this.table = table.getTable();
        this.field = field.getField();
        this.type = field.getType();
        this.length = field.getLength();
        this.autoIncrement = autoIncrement;
    }
    
    /**
     * Constructor.
     * 
     * @param table
     * @param field
     * @param autoIncrement 
     */
    public Table(String table, Field field, Boolean autoIncrement) {
        this.table = table;
        this.field = field.getField();
        this.type = field.getType();
        this.length = field.getLength();
        this.autoIncrement = autoIncrement;
    }

    /**
     * Add field to the table. When a field is assigned to this table then
     * the old field is replaced with your field.
     *
     * @param field
     */
    public void addField(Field field) {
        this.field = field.getField();
        this.type = field.getType();
        this.length = field.getLength();
    }

    /**
     * Check wether the primary key of this table is auto increment or not.
     * 
     * @return Boolean.
     */
    public Boolean isAutoIncrement() {
        return autoIncrement;
    }
    
    /**
     * Get primary key of this table.
     *
     * @return primary key
     */
    public String getPrimaryKey() {
        return field[0];
    }

    /**
     * Get primary key type of this table.
     *
     * @return type of primary key
     */
    public String getPrimaryKeyType() {
        return type[0];
    }

    /**
     * Get the type of the specified field.
     *
     * @param field
     * @return type of specified field
     */
    public String getTypeByField(String field) {
        return type[Arrays.binarySearch(this.field, field)];
    }

    /**
     * Get table.
     *
     * @return table
     */
    public String getTable() {
        return table;
    }
    
    /**
     * Get field.
     * 
     * @return Field
     */
    public Field getField() {
        return new Field(field, type, length);
    }

    /**
     * Get field.
     *
     * @return String[]
     */
    public String[] getFieldString() {
        return field;
    }

    /**
     * Get type.
     *
     * @return String[]
     */
    public String[] getTypeString() {
        return type;
    }
    
    /**
     * Get length.
     * 
     * @return String[]
     */
    public String[] getLengthString() {
        return length;
    }
    
    /**
     * Check if the record is exist.
     * 
     * @param field
     * @param value
     * @return Boolean
     * @throws SQLException
     * @throws ClassNotFoundException 
     */
    public Boolean isExist(String field, String type, String value) throws SQLException, ClassNotFoundException {
        return Query.isExist(this, field, type, value);
    }
    
    /**
     * Create an auto increment from the field.
     * 
     * @return Boolean
     * @throws SQLException
     * @throws ClassNotFoundException 
     */
    public String getAutoIncrement() throws SQLException, ClassNotFoundException {
        return Query.getAutoIncrement(this);
    }
    
    /**
     * Create table.
     * 
     * @throws SQLException
     * @throws ClassNotFoundException 
     */
    public void create() throws SQLException, ClassNotFoundException {
        Query.createTable(this, new Field(field, type, length));
    }
    
    /**
     * Search from a database with a key.
     * 
     * @param key
     * @return ResultSet
     * @throws SQLException
     * @throws ClassNotFoundException 
     */
    public ResultSet search(String key) throws SQLException, ClassNotFoundException {
        return Query.search(this, key);
    }
    
    /**
     * Search from a database with a key.
     * 
     * @param field
     * @param key
     * @return ResultSet
     * @throws SQLException
     * @throws ClassNotFoundException 
     */
    public ResultSet search(String[] field, String key) throws SQLException, ClassNotFoundException {
        return Query.search(this, field, key);
    }
    
    /**
     * Count the total record on the table.
     *
     * @return total record
     * @throws SQLException
     * @throws ClassNotFoundException
     */
    public int count() throws SQLException, ClassNotFoundException {
        return Query.count(this);
    }
    
    /**
     * Count the total record on the table.
     *
     * @param where
     * @return total record
     * @throws SQLException
     * @throws ClassNotFoundException
     */
    public int count(Where where) throws SQLException, ClassNotFoundException {
        return Query.count(this, where);
    }
    
    /**
     * Execute a select query.
     * 
     * @return
     * @throws SQLException
     * @throws ClassNotFoundException 
     */
    public ResultSet select() throws SQLException, ClassNotFoundException {
        return Query.select(this, null, new Where(""));
    }
    
    /**
     * Execute a select query.
     * 
     * @param projection
     * @return ResultSet
     * @throws SQLException
     * @throws ClassNotFoundException 
     */
    public ResultSet select(String[] projection) throws SQLException, ClassNotFoundException {
        return Query.select(this, projection, new Where(""));
    }
    
    /**
     * Execute a select query.
     * 
     * @param projection
     * @param where
     * @return ResultSet
     * @throws SQLException
     * @throws ClassNotFoundException 
     */
    public ResultSet select(String[] projection, Where where) throws SQLException, ClassNotFoundException {
        return Query.select(this, projection, where);
    }
    
    /**
     * Execute a select query.
     * 
     * @param field
     * @param sortingType
     * @return
     * @throws SQLException
     * @throws ClassNotFoundException 
     */
    public ResultSet select(String field, String sortingType) throws SQLException, ClassNotFoundException {
        return Query.select(this, null, null, field, sortingType);
    }
    
    /**
     * Execute a select query.
     * 
     * @param projection
     * @param where
     * @param field
     * @param sortingType
     * @return ResultSet
     * @throws SQLException
     * @throws ClassNotFoundException 
     */
    public ResultSet select(String[] projection, Where where, String field, String sortingType) throws SQLException, ClassNotFoundException {
        return Query.select(this, projection, where, field, sortingType);
    }
    
    /**
     * Execute a select query with in where statement.
     * 
     * @param compared
     * @param notin
     * @return ResultSet
     * @throws SQLException
     * @throws ClassNotFoundException 
     */
    public ResultSet selectIn(String compared, ArrayList in) throws SQLException, ClassNotFoundException {
        return Query.selectIn(this, null, compared, Util.ObjectToArray(in.toArray()));
    }
    
    /**
     * Execute a select query with in where statement.
     * 
     * @param projection
     * @param compared
     * @param notin
     * @return ResultSet
     * @throws SQLException
     * @throws ClassNotFoundException 
     */
    public ResultSet selectIn(String[] projection, String compared, ArrayList in) throws SQLException, ClassNotFoundException {
        return Query.selectIn(this, projection, compared, Util.ObjectToArray(in.toArray()));
    }
    
    /**
     * Execute a select query with in where statement.
     * 
     * @param compared
     * @param in
     * @return
     * @throws SQLException
     * @throws ClassNotFoundException 
     */
    public ResultSet selectIn(String compared, String[] in) throws SQLException, ClassNotFoundException {
        return Query.selectIn(this, null, compared, in);
    }
    
    /**
     * Execute a select query with in where statement.
     * 
     * @param projection
     * @param compared
     * @param in
     * @return
     * @throws SQLException
     * @throws ClassNotFoundException 
     */
    public ResultSet selectIn(String[] projection, String compared, String[] in) throws SQLException, ClassNotFoundException {
        return Query.selectIn(this, projection, compared, in);
    }
    
    /**
     * Execute a select query with not in where statement.
     * 
     * @param compared
     * @param notin
     * @return ResultSet
     * @throws SQLException
     * @throws ClassNotFoundException 
     */
    public ResultSet selectNotIn(String compared, ArrayList notin) throws SQLException, ClassNotFoundException {
        return Query.selectNotIn(this, null, compared, Util.ObjectToArray(notin.toArray()));
    }
    
    /**
     * Execute a select query with not in where statement.
     * 
     * @param table
     * @param projection
     * @param compared
     * @param notin
     * @return ResultSet
     * @throws SQLException
     * @throws ClassNotFoundException 
     */
    public ResultSet selectNotIn(String[] projection, String compared, ArrayList notin) throws SQLException, ClassNotFoundException {
        return Query.selectNotIn(this, projection, compared, Util.ObjectToArray(notin.toArray()));
    }
    
    /**
     * Execute a select query with not in where statement.
     * 
     * @param compared
     * @param notin
     * @return
     * @throws SQLException
     * @throws ClassNotFoundException 
     */
    public ResultSet selectNotIn(String compared, String[] notin) throws SQLException, ClassNotFoundException {
        return Query.selectNotIn(this, null, compared, notin);
    }
    
    /**
     * Execute a select query with not in where statement.
     * 
     * @param table
     * @param projection
     * @param compared
     * @param notin
     * @return ResultSet
     * @throws SQLException
     * @throws ClassNotFoundException 
     */
    public ResultSet selectNotIn(String[] projection, String compared, String[] notin) throws SQLException, ClassNotFoundException {
        return Query.selectNotIn(this, projection, compared, notin);
    }

    /**
     * Insert a data into database.
     * 
     * @param value
     * @throws SQLException
     * @throws ClassNotFoundException 
     */
    public void insert(String[] value) throws SQLException, ClassNotFoundException {
        Query.insert(this, value);
    }
    
    /**
     * Update existing data on database.
     * 
     * @param value
     * @param primaryValue
     * @throws SQLException
     * @throws ClassNotFoundException 
     */
    public void update(String[] value, String primaryValue) throws SQLException, ClassNotFoundException {
        update(new Field(this.field, this.type, this.length), value, primaryValue);
    }
    
    /**
     * Update existing data on database.
     * 
     * @param field
     * @param value
     * @param primaryValue
     * @throws SQLException
     * @throws ClassNotFoundException 
     */
    public void update(Field field, String[] value, String primaryValue) throws SQLException, ClassNotFoundException {
        if (Query.isUseFlank(this.getPrimaryKeyType())) {
            primaryValue = TextUtil.flank(primaryValue, "'");
        }
        Query.update(this, field, value, new Where(this.getPrimaryKey()+"="+primaryValue));
    }
    
    /**
     * Update existing data on database.
     * 
     * @param value
     * @param where
     * @throws SQLException
     * @throws ClassNotFoundException 
     */
    public void update(String[] value, Where where) throws SQLException, ClassNotFoundException {
        update(new Field(this.field, this.type, this.length), value, where);
    }
    
    /**
     * Update existing data on database.
     * 
     * @param field
     * @param value
     * @param where
     * @throws SQLException
     * @throws ClassNotFoundException 
     */
    public void update(Field field, String[] value, Where where) throws SQLException, ClassNotFoundException {
        Query.update(this, field, value, where);
    }
    
    /**
     * Delete data from database.
     * 
     * @param value
     * @throws SQLException
     * @throws ClassNotFoundException 
     */
    public void delete(String value) throws SQLException, ClassNotFoundException {
        Query.delete(this, this.getPrimaryKey(), value);
    }
    
    /**
     * Empty the records of this table.
     * 
     * @throws SQLException
     * @throws ClassNotFoundException 
     */
    public void truncate() throws SQLException, ClassNotFoundException {
        Query.truncate(this);
    }
    
    /**
     * Delete or drop this table.
     * 
     * @throws SQLException
     * @throws ClassNotFoundException 
     */
    public void drop() throws SQLException, ClassNotFoundException {
        Query.dropTable(this);
    }

}